Skip to main content

📊 Vendo Sales Terminal Report

Generate a centralized sales dashboard report from all JuanFi vending machines, displaying real-time metrics including total sales, current balance, daily/monthly revenue in a formatted system note. Pulls data via API from multiple vendos, processes timestamps in 12-hour format, and compiles everything into a single readable report updated hourly or on-demand.

info

Report includes:

  • Vendo names and IP addresses
  • Total accumulated sales
  • Current balance in machine
  • Daily sales total
  • Monthly sales total
  • Timestamp of last update
  • Error handling for offline vendos

Prerequisites​

  • ✅ MikroTik RouterOS device with HTTP client capability
  • ✅ Multiple JuanFi vendos with API endpoints:
    • /admin/api/getSystemConfig (vendo name, data)
    • /admin/api/dashboard (balance, sales data)
  • ✅ Vendo static IP addresses configured
  • ✅ API key for authentication
  • ✅ Access to RouterOS console (SSH, Winbox, or WinBox)
  • ✅ RouterOS v6.48+
warning

API Response Format: This script expects JSON responses with specific fields. Verify your vendo firmware matches expected API format before deploying.

Configuration Steps​

Option A: Terminal Configuration​

  1. Access the terminal:

    ssh admin@your-router-ip
  2. Create the dashboard script:

    /system script add name="vendo-sales-dashboard" source={
    :local vendos {"10.1.1.2"; "10.1.2.2"; "10.1.3.2";};
    :local apiKey "pqa92jwxrk";

    # Format current time as 12-hour (2:30 PM format)
    :local itime [/system clock get time];
    :local minsec [:pick $itime 2 8];
    :local mhours [:tonum [:pick $itime 0 2]];
    :local msymbl "AM";
    :if ($mhours > 11) do={:set msymbl "PM"};
    :set mhours ($mhours % 12);
    :if ($mhours = 0) do={:set mhours 12};
    :if ($mhours < 10) do={:set mhours "0$mhours"};
    :local mtime "$mhours$minsec $msymbl";

    # String split helper function
    :global split do={
    :local array;
    :for i from=0 to=([:len $string] - 1) do={
    :local char [:pick $string $i];
    :if ($char = "|") do={
    :set $char ",";
    };
    :set array ($array . $char);
    };
    :return ([:toarray $array]);
    };

    # Build report rows
    :local row "";
    :foreach vendo in=$vendos do={
    /do {
    :log warning "Getting data from $vendo";
    :local settings [$split string=([ /tool fetch http-method=post \
    http-header-field="X-TOKEN: $apiKey" \
    url="http://$vendo/admin/api/getSystemConfig" \
    output="user" as-value ]->"data")];
    :local infos [$split string=([ /tool fetch http-method=post \
    http-header-field="X-TOKEN: $apiKey" \
    url="http://$vendo/admin/api/dashboard" \
    output="user" as-value ]->"data")];
    :local sales [toarray ([/system script get [find name=($settings->0)] comment])];
    :local newRow "$($settings->0)\t\t$vendo\t$($infos->1)\t$($infos->2)\t$($sales->3)\t$($sales->1)\r\n";
    :set row ($row . $newRow);
    } on-error={
    :log error "ERROR! $vendo OFFLINE";
    :local newRow "error! - offline\t$vendo\r\n";
    :set row ($row . $newRow);
    }
    }

    # Get daily and monthly income from scripts
    :local todayincome ([/system script get [find name=todayincome] source]);
    :local monthlyincome ([/system script get [find name=monthlyincome] source]);

    # Update system note with report
    /system note set note=\
    "==============================================================================\r\
    \n\t\t TERMINAL VENDO SALES REPORT by AZK-TECH\r\
    \n\t\t Updated on: $([/system clock get date]) $mtime\r\
    \n\t\tDAILY: $todayincome\t\t\tMONTHLY: $monthlyincome\r\
    \n==============================================================================\r\
    \nNAME\t\t\tIP ADDRESS\tTOTAL\tCURRENT\tDAILY\tMONTHLY\r\n$row";

    :log warning "Dashboard update complete";
    }
  3. Schedule hourly updates:

    /system scheduler add name="vendo-dashboard-hourly" on-event="vendo-sales-dashboard" \
    start-time=00:00:00 interval=1h comment="Update vendo sales dashboard"
  4. View the dashboard:

    /system note print

Option B: Winbox Configuration​

  1. Navigate to System > Scripts:

    • Click +
    • Name: vendo-sales-dashboard
    • Paste full script from Option A step 2
    • Click OK
  2. Navigate to System > Scheduler:

    • Click +
    • Name: vendo-dashboard-hourly
    • On Event: vendo-sales-dashboard
    • Start Time: 00:00:00
    • Interval: 1h
    • Click OK
  3. View dashboard:

    • Navigate to System > System Notes
    • Should display formatted sales report

Understanding the Script​

Time Formatting Logic​

:local itime [/system clock get time]     # Get 24-hour time (14:30:45)
:local minsec [:pick $itime 2 8] # Extract :30:45
:local mhours [:tonum [:pick $itime 0 2]] # Extract 14, convert to number

:if ($mhours > 11) do={:set msymbl "PM"} # PM if > 11
:set mhours ($mhours % 12) # Convert to 12-hour (14 % 12 = 2)
:if ($mhours = 0) do={:set mhours 12} # Midnight = 12

Examples:

  • 14:30:45 → 2:30:45 PM
  • 09:15:20 → 9:15:20 AM
  • 00:45:00 → 12:45:00 AM

String Split Function​

:global split do={ 
:local array;
:for i from=0 to=([:len $string] - 1) do={
:local char [:pick $string $i];
:if ($char = "|") do={
:set $char ","; # Convert pipe | to comma
};
:set array ($array . $char);
};
:return ([:toarray $array]); # Convert to array
};

Converts pipe-delimited strings to RouterOS arrays for easy indexing.

API Data Fetching​

/tool fetch http-method=post \
http-header-field="X-TOKEN: $apiKey" \
url="http://$vendo/admin/api/getSystemConfig" \
output="user" as-value

Returns: {"data": "name|model|version|..."} → Parsed into array → Index as needed

Report Row Building​

:local newRow "$($settings->0)\t\t$vendo\t$($infos->1)\t...\r\n"
  • $settings->0 - Vendo name
  • $vendo - IP address
  • $infos->1 - Total sales
  • $infos->2 - Current balance
  • Etc.

Verification​

  1. Test script manually:

    /system script run vendo-sales-dashboard
  2. Check system note:

    /system note print

    Should display formatted report with all vendos.

  3. Verify API responses:

    curl -H "X-TOKEN: pqa92jwxrk" http://10.1.1.2/admin/api/getSystemConfig
    curl -H "X-TOKEN: pqa92jwxrk" http://10.1.1.2/admin/api/dashboard
  4. Monitor scheduler:

    /system scheduler print
  5. Check logs:

    /log print where topics~"system"

Troubleshooting​

IssueCauseSolution
Empty/blank reportVendos offline or API unreachablePing vendo: ping 10.1.1.2; test API manually with curl
"Unknown identifier" errorVariable name typo or syntaxVerify: $split, $toarray, -> operator syntax
Time format wrongTime format logic issueCheck /system clock print; verify modulo math (% 12)
Missing data fieldsAPI response format changedVerify vendo firmware; check API documentation; adjust array indices
Report shows all "offline"API key invalidTest with curl; verify key matches vendo config
Scheduler doesn't runInterval set incorrectlyVerify interval: 1h (1 hour), 30m (30 minutes), etc.
Truncated reportReport too long for system noteReduce number of fields or consolidate data

Advanced Options​

Run every 30 minutes instead:​

/system scheduler set [find name=vendo-dashboard-hourly] interval=30m

Add network status indicator:​

:foreach vendo in=$vendos do={
:local status "✓ Online";
/do {
/tool fetch url="http://$vendo/admin/api/dashboard" output="none" timeout=2s
} on-error={
:set status "✗ Offline";
}
}

Email report instead of system note:​

/tool e-mail send to="admin@example.com" subject="Vendo Sales Report" body="$reportText"

Export report to file:​

/file print file="vendo-sales-report.txt" >> "$reportText";

Add vendo temperature/humidity data:​

:local environment [$split string=([ /tool fetch http-method=post \
http-header-field="X-TOKEN: $apiKey" \
url="http://$vendo/admin/api/getEnvironment" \
output="user" as-value ]->"data")];

Create dashboard with pie/bar charts:​

Generate CSV and import to Excel/Grafana for visualizations.

Alert if any vendo offline for > 1 hour:​

:if ($offlineCount > 0) do={
:local botApi "123456789:ABCDefGHIJKlmNOpqrsTUvwxYZ";
:local chatId "-123456789";
/tool fetch url="https://api.telegram.org/bot$botApi/sendMessage?chat_id=$chatId&text=🚨%20$offlineCount%20vendos%20offline" keep-result=no;
}

Compare sales vs previous day/month:​

:local previousDayTotal 5000;  # Manually track or store
:local todayTotal 5500;
:local percentChange (($todayTotal - $previousDayTotal) / $previousDayTotal * 100);

Sample Report Output​

==============================================================================
TERMINAL VENDO SALES REPORT by AZK-TECH
Updated on: 2026-01-31 2:45:30 PM
DAILY: 5500 PHP MONTHLY: 125000 PHP
==============================================================================
NAME IP ADDRESS TOTAL CURRENT DAILY MONTHLY
Vendo 01 10.1.1.2 15000 1200 1800 45000
Vendo 02 10.1.2.2 12500 950 1500 38000
Vendo 03 10.1.3.2 error! - offline

Best Practices​

  1. Check API format with vendo provider before deployment
  2. Test with one vendo first before adding all
  3. Store previous totals to calculate growth trends
  4. Schedule during off-peak to avoid network congestion
  5. Set up alerts for offline vendos
  6. Monitor report consistency - sudden drops may indicate data loss
  7. Back up reports to external server weekly

Completion​

✅ Vendo sales dashboard is now active!

Next steps:

  • Run script manually to verify format
  • Set up hourly scheduler
  • Share dashboard view with management
  • Add Telegram/email alerts for offline vendos
  • Export data to Excel for trend analysis
  • Back up configuration: /system backup save